package com.qinchen.boot.config;

import ch.qos.logback.core.db.DBHelper;
import com.qinchen.boot.bean.Pet;
import com.qinchen.boot.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.util.UrlPathHelper;

/**
 * @author qinchen
 * @date 2021/1/21 10:55 下午
 * 向未来的自己致敬
 * 描述：Configuration 告诉Springboot，这是一个配置类
 * 此配置类本身也是bean
 * @Configuration(proxyBeanMethods = true) -> 代理bean方法=true
 *      意味着 MyConfig 是被CJLIB代理的对象
 *      若将proxyBeanMethods=false，则MyConfig将不是代理对象，两次获取配置类中的注册的bean，都是重新创建一个新的对象
 *      proxyBeanMethods = false|true 全（Full模式）与轻（Lite）模式
 *      配置类组件之间无依赖关系用Lite模式，加速容器启动过程
 *      配置类组件之间有依赖关系，方法会被调用得到之前单实例组件，用Full模式
 * @Import 可以导入bean，名字默认是类的全限定名
 *      com.qinchen.boot.bean.User
 *      ch.qos.logback.core.db.DBHelper
 *
 * @ImportResource("classpath:beans.xml")
 *      导入早期的xml方式配置文件中配置的bean
 *
 * @EnableConfigurationProperties(CarProperties.class)
 *      这是第二种注入配置信息到bean的方式，一般用于给第三方类注入属性
 *      这种方式就可以省略Car上的@Component注解
 */
@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = true)
//@ImportResource("classpath:beans.xml")
//@EnableConfigurationProperties(CarProperties.class)
public class MyConfig implements WebMvcConfigurer {

    /**
     * 以方法名作为bean的id
     * 返回类型就是bean的类型
     * 返回的bean就是容器中的实例，默认是单例
     * @return
     */
    @Bean
    public User user01(){
        return new User("qinchen", 18);
    }

    @Bean("tomcat")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }

    /**
     * @ConditionalOnBean 按条件加载bean
     * 也可以加载类上，道理一样
     * @ConditionalOnMissingBean 不存在某个bean时
     * 其他可以看Condition的子注解
     * @return
     */
    @ConditionalOnBean(name = "tomcat2")
    //@ConditionalOnMissingBean(name = "user02")
    @Bean("wangcai")
    public Pet wangCaiPet(){
        System.out.println("创建 wangCaiPet Bean");
        return new Pet("wangcai");
    }

    /**
     * 方法一
     * @param configurer
     */
//    @Override
//    public void configurePathMatch(PathMatchConfigurer configurer) {
//        UrlPathHelper urlPathHelper = new UrlPathHelper();
//        // 开启矩阵变量支持
//        urlPathHelper.setRemoveSemicolonContent(false);
//        configurer.setUrlPathHelper(urlPathHelper);
//    }

    /**
     * 方法二
     * @return
     */
    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            @Override
            public void configurePathMatch(PathMatchConfigurer configurer) {
                UrlPathHelper urlPathHelper = new UrlPathHelper();
                // 开启矩阵变量支持
                urlPathHelper.setRemoveSemicolonContent(false);
                configurer.setUrlPathHelper(urlPathHelper);
            }

            /**
             * 自定义参数类型解析器
             * @param registry
             */
            @Override
            public void addFormatters(FormatterRegistry registry) {
                registry.addConverter(new Converter<String, Pet>() {
                    @Override
                    public Pet convert(String s) {
                        // 这里面写解析逻辑
                        if(!StringUtils.isEmpty(s)){
                            Pet pet = new Pet();
                            String[] split = s.split(",");
                            pet.setName(split[0]);
                            return pet;
                        }
                        return null;
                    }
                });
            }
        };
    }
}
